package cn.itsource.itsource.service.impl;

import cn.itsource.itsource.domain.User;
import cn.itsource.itsource.config.WechartProperties;
import cn.itsource.itsource.domain.Wxuser;
import cn.itsource.itsource.dto.BinderDto;
import cn.itsource.itsource.dto.WechartTokenDto;
import cn.itsource.itsource.dto.WechartUserInfoDto;
import cn.itsource.itsource.mapper.UserMapper;
import cn.itsource.itsource.mapper.WxuserMapper;
import cn.itsource.itsource.service.IWechartService;
import cn.itsource.itsource.service.RedisService;
import cn.itsource.itsource.util.AjaxResult;
import cn.itsource.itsource.util.HttpUtil;
import cn.itsource.itsource.util.MD5;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.UUID;

@Service
@Transactional
public class WechartServiceImpl implements IWechartService {
    @Autowired
    private WechartProperties wechartProperties;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WxuserMapper wxuserMapper;
    @Autowired
    private RedisService redisService;



    @Override
    public AjaxResult callback(String code, String state) {
        //第3步：当进入到回调这个方法时，则说明已经成功获取了 【授权码】

        //第4步：根据授权码来获取access_token令牌
        String tokenUrl = String.format(wechartProperties.getTokenUrl(), wechartProperties.getAppId(), wechartProperties.getAppSecrect(), code);

        //第5步：在后台通过授权码换取令牌的url，向微信后台发送http请求并返回token
        HttpUtil httpUtil = new HttpUtil(tokenUrl);//在创建http连接时，先把url地址传进来
        httpUtil.get();//发送了get请求
        //{"access_token":"50_U-Aqn2NqabxKCqDRpIsL2YgvLfAX5INqU72SAKTNIEtsJET-Fqtq1aDzUJIkT-EC2ew6RZYWPJvX1xkR4vJZkjXtgDh4aIUIbpIATEmhpKg", 令牌
        // "expires_in":7200,
        // "refresh_token":"50_bYE8JQcoCONSczcHkVbJGsC5oO9s7QkU96laOj5vKq-uWXcOQyyw3RVGt2xr41bPG8PNWcgQ283JKzxws1aiFz5E0ptKCVKfpBPsub6X18U",
        // "openid":"oa9wA094PPuJLen6cn6ANLUuRyso", 这个值就是当前扫码微信用户的微信号的加密值 open_id
        // "scope":"snsapi_login",
        // "unionid":"ovnCWw-V2UB_lGq0tXi7Wjtp2Izg"}
        String content = httpUtil.getContent();//获取请求后返回的结果

        //第6步：将返回的Token信息，通过Fastjson转换为一个对象
        WechartTokenDto wechartTokenDto = JSONObject.parseObject(content, WechartTokenDto.class);

        //第7步：根据令牌获取当前微信用户的用户信息
        String userinfoUrl = String.format(wechartProperties.getUserinfoUrl(), wechartTokenDto.getAccess_token(), wechartTokenDto.getOpenid());
        //根据拼接的url地址，向微信服务器，发送请求并获取用户的个人信息
        httpUtil = new HttpUtil(userinfoUrl);
        httpUtil.get();
        String userContent = httpUtil.getContent();
        WechartUserInfoDto wechartUserInfoDto = JSONObject.parseObject(userContent, WechartUserInfoDto.class);

        //在获取到微信用户信息后，接下来，就会与我们自己系统的业务进行对接
       /* //在获取到微信用户信息后，接下来，就会与我们自己系统的业务进行对接
        //1.如果是纯新用户登录，则直接添加t_wxuser，然后跳到binder.html页面

        //2. 用户如果曾经扫过码，但是没有进行绑定操作

        //2.1 检查openid值是否存在，如果存在，还要进行下一步校验

        //2.2 校验t_wxuser表关联的user_id的值，是否为空，如果不为空，接着到t_user表查询 user信息

        //2.3 如果查到user信息，再检查手机号是否为空，如果为空，跳绑定页面

        //3. 用户扫过了码，也绑定了手机号，那就直接 跳登录成功页面
*/

        //在把实现业务思路分析完整后，写代码之前，再针对分析的思路，进行再次的梳理和整合
        //TODO 原则：当判断情况很多的时候，先将所有不满足条件的判断全部验证完，剩下的就是一定满足的
        //1. 先扫码【已完成】


        //前面需要一堆的校验
        //a1. t_wxuser已经存在了openid，不需要再添加到t_wxuser=====>
//      再判断t_wxuser中的user_id是否为空或者user_id在t_user表中找不到手机号
        //a1-1: t_wxuser已经存在了openid
        Wxuser wxuser = wxuserMapper.findByOpenId(wechartUserInfoDto.getOpenid());
        if(wxuser==null){
            //添加数据到t-wxuser 直接跳绑定
            wxuser=new Wxuser();
            BeanUtils.copyProperties(wechartUserInfoDto,wxuser);//将一个对象中的数据复制到另一个新对象中（复制原则：属性名相同且属性数据类型相同）
            wxuserMapper.save(wxuser);
            return AjaxResult.error("请绑定手机号").setData(wechartUserInfoDto.getOpenid());
        }


        //a1-2 : 如果wxuser中查到了数据，接着判断user_id是否为空或者user_id在t_user表中找不到手机号
        if(wxuser.getOpenid()==null){

            return AjaxResult.error("请绑定手机号").setData(wechartUserInfoDto.getOpenid());
        }
        //a1-3 : user_id在t_user表中找不到手机号
        User user=userMapper.findByUserId(wxuser.getUserId());
        if(user==null|| StringUtils.isBlank(user.getPhone())){

            return AjaxResult.error("请绑定手机号").setData(wechartUserInfoDto.getOpenid());
        }
        return AjaxResult.success("获取成功").setData(wechartUserInfoDto);


    }

    @Override
    public AjaxResult binder(BinderDto dto) {
        //思路分析：绑定的操作：最终目的是要将当前关联的openid对应的微信用户信息与t_user表进行关联
        //判断原则：根据openid查t_wxuser表，再根据t_wxuser的user_id对应上t_user表的id
        //1. 验证（主要验证手机号为空+验证码为空+验证码是否正确）
        //验证码是否正确
        String code = redisService.getKeyObjectValue(dto.getPhone(), String.class);
        if (!StringUtils.equals(code, dto.getCode())) {
            return AjaxResult.error("验证码不正确");
        }

        //2. 根据openid查t_wxuser的信息
        Wxuser wxuser = wxuserMapper.findByOpenId(dto.getOpenid());
        //2.1 根据查到的t_wxuser信息中的user_id进行判断
        if (wxuser.getUserId() == null) {
            //2.2 如果是空的，则直接新增一条t_user的数据,同时将新增的id保存到t_wxuser中的user_id字段
            User user = new User();
            user.setPhone(dto.getPhone());
            //在保存密码时，可以对密码进行加密处理 md5(不可逆）
            //salt盐：加盐的目的，就是为了让md5的破解变的更难
            String salt = UUID.randomUUID().toString().replace("-", "");
            user.setSalt(salt);
            user.setPassword(MD5.getMD5("123456" + salt));
            user.setCreatetime(new Date());
            user.setState(0);
            userMapper.register(user);
            //同时将新增的id保存到t_wxuser中的user_id字段
            wxuser.setUserId(user.getId());
            //执行update操作
            wxuserMapper.updateOfUserId(wxuser);
        }else {
            //2.3 如果不是空的，根据user_id查出t_user的数据。然后将phone更新上去
            User user = userMapper.findByUserId(wxuser.getUserId());
            user.setPhone(dto.getPhone());
            userMapper.updateOfPhone(user);
        }

        return AjaxResult.success("绑定成功");
    }
}
